#include "command.h"
pthread_mutex_t log_queue_mutex;
int log_fd; // 日志文件描述符

void print_files_in_dir(void)
{
    DIR *dir;
    struct dirent *entry;
    struct stat file_stat;

    dir = opendir(".");
    ERROR_CHECK(dir, NULL, "opendir");

    // 遍历目录下的所有文件
    printf("您本地目录下有这些文件: ");
    while ((entry = readdir(dir)) != NULL)
    {
        // 过滤掉 . 和 ..（仅显示文件）,                                           仅显示普通文件（排除目录）
        if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0 && stat(entry->d_name, &file_stat) == 0 && S_ISREG(file_stat.st_mode))
        {
            printf("  %s", entry->d_name);
        }
    }
    printf("\n");

    closedir(dir);

    return;
}

int validate_and_parse_command(int sockfd, int log_fd)
{
    printf("请输入命令: ");
    char command[1024];
    fgets(command, sizeof(command), stdin);
    if (strlen(command) == 0)
    {
        LOG_INFO(log_fd, LOG_WARN, "输入为空"); // 记录输入为空的警告
        printf("输入为空\n"); // 这个判断是用来避免直接输入回车导致未定义行为
        return -1;
    }
    command[strlen(command) - 1] = '\0'; // 安全去除换行符

    // 分割命令并统计参数总数
    char *args[MAX_ARGS] = {0};
    int arg_count = 0;
    char *token = strtok(command, " ");
    while (token != NULL && arg_count < MAX_ARGS)
    {
        args[arg_count++] = token;
        token = strtok(NULL, " ");
    }

    // 无参数或命令无效
    if (arg_count == 0 || get_command_type(args[0]) == CMD_UNKNOWN)
    {
        LOG_INFO(log_fd, LOG_WARN, "命令无效");
        printf("命令无效\n");
        return -1;
    }

    train_t train, recv_train; // recv_train这个用来收,免得相互污染
    train.type = get_command_type(args[0]);
    int commandType = train.type; // 这里记录一下,因为后面会用同一个小火车收,会覆盖train.type

    switch (train.type)
    {
    case CMD_CD:
        if (arg_count > 2)
        { // 命令名+1个参数为合法上限
            LOG_INFO(log_fd, LOG_WARN, "CMD_CD 参数数量错误 (需1个, 实际:%d)", arg_count - 1);
            printf("错误：参数过多\n");
            return -3;
        }
        break;
    case CMD_PUTS:
    case CMD_GETS:
    case CMD_RM:
    case CMD_MKDIR:
    case CMD_RMDIR:
        if (arg_count != 2)
        { // 必须且只能有1个参数
            LOG_INFO(log_fd, LOG_WARN, "CMD_%s 参数数量错误 (需1个, 实际:%d)", args[0], arg_count - 1);
            printf("错误: 需制定一个参数\n");
            return -2;
        }
        break;
    default:
        if (arg_count > 1)
        { // 其他命令最多1个参数
            LOG_INFO(log_fd, LOG_WARN, "CMD_%s 参数数量错误 (不要参数, 实际:%d)", args[0], arg_count - 1);
            printf("错误：参数过多\n");
            return -3;
        }
    }

    // 处理合法参数并发送命令
    if (arg_count >= 2)
    {
        // 这里虽然我们都只实现了命令只跟一个文件或目录, 但是为了可拓展性我这里还是写>=2
        train.length = strlen(args[1]);
        memcpy(train.value, args[1], train.length);
    }
    else
    {
        // 无参数的默认逻辑
        train.length = 0;
        bzero(train.value, sizeof(train.value));

        // 针对 CD 命令的特殊处理
        if (train.type == CMD_CD)
        {
            // 默认切换到根目录"/"
            const char *default_path = "/";
            train.length = strlen(default_path);
            memcpy(train.value, default_path, train.length);
        }

        if (train.type == CMD_EXIT)
        {
            send(sockfd, &train, sizeof(train.type) + sizeof(train.length) + train.length, MSG_NOSIGNAL);
            exit(0);
        }
    }

    // 发送命令到服务端
    send(sockfd, &train, sizeof(train.type) + sizeof(train.length) + train.length, MSG_NOSIGNAL);
    if (commandType == CMD_PUTS)
    {
        sendFile(train.value, sockfd, log_fd); // 执行上传
    }
    else if (commandType == CMD_GETS)
    {
        recvFile(sockfd, train.value, log_fd); // 执行下载
    }
    // 接收命令是否成功的响应
    recv(sockfd, &recv_train.type, sizeof(recv_train.type), MSG_WAITALL);
    recv(sockfd, &recv_train.length, sizeof(recv_train.length), MSG_WAITALL);
    recv(sockfd, recv_train.value, recv_train.length, MSG_WAITALL);
    recv_train.value[recv_train.length] = '\0';
    if(recv_train.type == RESPON_ERROR)
    {
        LOG_INFO(log_fd, LOG_ERROR, "命令执行失败: %s", recv_train.value);
        printf("错误: %s\n", recv_train.value);
        return -1;
    }
    printf("%s\n", recv_train.value);

    // // 根据相应决定是否执行文件传输
    // if (strstr(recv_train.value, "Ready") != NULL)
    // { // 若服务器返回准备就绪

    // }

    return 0;
}

CommandType get_command_type(const char *input)
{
    if (strcmp(input, "cd") == 0)
        return CMD_CD;
    if (strcmp(input, "ls") == 0)
        return CMD_LS;
    if (strcmp(input, "pwd") == 0)
        return CMD_PWD;
    if (strcmp(input, "puts") == 0)
        return CMD_PUTS;
    if (strcmp(input, "gets") == 0)
        return CMD_GETS;
    if (strcmp(input, "mkdir") == 0)
        return CMD_MKDIR;
    if (strcmp(input, "rmdir") == 0)
        return CMD_RMDIR;
    if (strcmp(input, "exit") == 0)
        return CMD_EXIT;
    if (strcmp(input, "rm") == 0)
        return CMD_RM;

    return CMD_UNKNOWN; // 默认返回未知命令
}